﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Communicate
{
    /// <summary>
    /// WEB服务通信管理类。
    /// </summary>
    public class CommunicateManage
    {
        //接口与类型的映射。
        static Dictionary<string, Type> dict = null;
        /// <summary>
        /// 登录校验。
        /// </summary>
        static LoginCheckDelegate LoginCheck;
        /// <summary>
        /// 初始化WEB服务通信管理类。
        /// </summary>
        /// <param name="list">需要加载的程序集</param>
        /// <param name="loginCheck">登录校验的委托。</param>
        public static void Init(IEnumerable<Assembly> list, LoginCheckDelegate loginCheck)
        {
            if (dict != null)
                return;
            dict = new Dictionary<string, Type>();
            LoginCheck = loginCheck;
            HashSet<string> hash = new HashSet<string>();
            foreach (Assembly interfaceDll in list)
            {
                foreach (Type type in interfaceDll.GetExportedTypes().Where(t => t.IsInterface))
                {
                    hash.Add(type.FullName);
                }
            }
            foreach (Assembly classDll in list)
            {
                foreach (Type type in classDll.GetExportedTypes().Where(t => t.IsClass))
                {
                    dict[type.FullName] = type;
                    foreach (Type inter in type.GetInterfaces())
                    {
                        if (hash.Contains(inter.FullName))
                        {
                            dict[inter.FullName] = type;
                        }
                    }
                }
            }
        }
        public static LoginResult Login(string userCode, string password, System.Web.SessionState.HttpSessionState session)
        {
            LoginResult loginResult = new LoginResult();
            string message;
            object context;
            loginResult.Result = LoginCheck(userCode.Replace("\"", ""), password.Replace("\"", ""), out message, out context);
            loginResult.Message = message;
            session["JRC_Context"] = context;
            return loginResult;
        }
        public static object GetContext(System.Web.SessionState.HttpSessionState session)
        {
            return session["JRC_Context"];
        }
        /// <summary>
        /// 获取服务器数据处理接口。
        /// </summary>
        /// <typeparam name="T">接口类型。</typeparam>
        /// <returns>数据处理接口实例。</returns>
        public static T GetInstance<T>(object context)
        {
            return (T)CreateInstance(dict[typeof(T).FullName], context);
        }
        // 执行反射。
        internal static object Invoke(InvokeEntity entity, object context)
        {
            Type daoType = dict[entity.Interfaces];
            return daoType.InvokeMember(entity.Method, BindingFlags.InvokeMethod, null, CreateInstance(daoType, context), entity.Parameters);
        }
        // 执行反射。
        internal static object Invoke(string interfaces, string method, List<string> pars, object context)
        {
            Type daoType = dict[interfaces];
            foreach (MethodInfo item in daoType.GetMethods().Where(t => t.Name == method))
            {
                var parametersInfo = item.GetParameters();
                if (parametersInfo.Length == pars.Count)
                {
                    object[] parameters = new object[parametersInfo.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        parameters[i] = JsonSerializer.Deserialize(pars[i], parametersInfo[i].ParameterType);
                    }
                    return item.Invoke(CreateInstance(daoType, context), parameters);
                }
            }
            throw new Exception(string.Format("{0}.{1} 的 {2} 个参数的方法没找到", interfaces, method, pars.Count));
        }
        static object CreateInstance(Type type, object context)
        {
            foreach (var constructor in type.GetConstructors())
            {
                var pars = constructor.GetParameters();
                if (pars.Length == 1 && pars[0].ParameterType == typeof(object)) // 如果有IContext的构造函数，则优先调用。
                {
                    return constructor.Invoke(new object[] { context });
                }
            }
            return Activator.CreateInstance(type);
        }
    }
    /// <summary>
    /// 登录校验的委托。
    /// </summary>
    /// <param name="userCode">用户名。</param>
    /// <param name="password">密码。</param>
    /// <returns>校验结果。</returns>
    public delegate bool LoginCheckDelegate(string userCode, string password, out string message, out object context);
}
